#include "stdafx.h"
#include "../client/DCPlusPlus.h"
#include "Resource.h"

#include "WinampFrame.h"
#include "WinUtil.h"
#include "Winamp.h"
#include "../client/File.h"
#include "../client/StringTokenizer.h"

LRESULT WinampFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{

	CreateSimpleStatusBar(ATL_IDS_IDLEMESSAGE, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP);
	ctrlStatus.Attach(m_hWndStatusBar);

	ctrlPlay.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
		BS_PUSHBUTTON , 0, IDC_PLAY);
	ctrlPlay.SetWindowText(CTSTRING(WINAMP_PLAY));
	ctrlPlay.SetFont(WinUtil::systemFont);

	ctrlStop.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
		BS_PUSHBUTTON , 0, IDC_STOP);
	ctrlStop.SetWindowText(CTSTRING(WINAMP_STOP));
	ctrlStop.SetFont(WinUtil::systemFont);

	ctrlPause.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
		BS_PUSHBUTTON , 0, IDC_PAUSE);
	ctrlPause.SetWindowText(CTSTRING(WINAMP_PAUSE));
	ctrlPause.SetFont(WinUtil::systemFont);

	ctrlRefresh.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
		BS_PUSHBUTTON , 0, IDC_REFRESH_WINAMP);
	ctrlRefresh.SetWindowText(CTSTRING(WINAMP_REFRESH));
	ctrlRefresh.SetFont(WinUtil::systemFont);

	ctrlPosition.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE, 0, IDC_POSITION);
	trackBarContainer.SubclassWindow(ctrlPosition.m_hWnd);

	ctrlList.Attach(GetDlgItem(IDC_WINAMP_LIST));
	ctrlList.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | 
		WS_HSCROLL | WS_VSCROLL | LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SINGLESEL, WS_EX_CLIENTEDGE, IDC_WINAMP_LIST);

	ctrlList.SetExtendedListViewStyle(BOOLSETTING(FULL_ROW_SELECT) ? LVS_EX_FULLROWSELECT : 0 | LVS_EX_HEADERDRAGDROP);

	ctrlList.SetBkColor(WinUtil::bgColor);
	ctrlList.SetTextBkColor(WinUtil::bgColor);
	ctrlList.SetTextColor(WinUtil::textColor);

	ctrlList.InsertColumn(0, CTSTRING(WINAMP_ARTIST), LVCFMT_LEFT, 100, 0);
	ctrlList.InsertColumn(1, CTSTRING(WINAMP_TITLE), LVCFMT_LEFT, 100, 1);
	ctrlList.InsertColumn(2, CTSTRING(WINAMP_LENGTH), LVCFMT_LEFT, 100, 1);

	ctrlList.InsertColumn(3, CTSTRING(FILENAME), LVCFMT_LEFT, 150, 0);
	ctrlList.InsertColumn(4, CTSTRING(PATH), LVCFMT_LEFT, 300, 0);

	loadAll();
	
	m_hMenu = WinUtil::mainMenu;

	bHandled = FALSE;
	return 1;
}

LRESULT WinampFrame::onClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
	if(!closed){
		TimerManager::getInstance()->removeListener(this);
		ctrlList.DeleteAllItems();

		bHandled = TRUE;
		closed = true;
		PostMessage(WM_CLOSE);
		return 0;
	} else {
		MDIDestroy(m_hWnd);
		return 0;
	}
}

void WinampFrame::UpdateLayout(BOOL bResizeBars /* = TRUE */)
{
	RECT rect;
	GetClientRect(&rect);

	UpdateBarsPosition(rect, bResizeBars);
	setStatus();

	CRect rc = rect;
	rc.top += 2;
	rc.bottom -= 28;
	ctrlList.MoveWindow(rc);

	const long bwidth = 90;
	const long bspace = 10;

	rc = rect;

	rc.bottom -= 2;
	rc.top = rc.bottom - 22;

	rc.left = 2;
	rc.right = rc.left + bwidth;
	ctrlPlay.MoveWindow(rc);

	rc.left = bspace + rc.right;
	rc.right = rc.left + bwidth;
	ctrlPause.MoveWindow(rc);

	rc.left = bspace + rc.right;
	rc.right = rc.left + bwidth;
	ctrlStop.MoveWindow(rc);

	rc.left = bspace + rc.right;
	rc.right = rc.left + bwidth;
	ctrlRefresh.MoveWindow(rc);

	rc.left = bspace + rc.right;
	rc.right = rect.right - 20;
	ctrlPosition.MoveWindow(rc);
	
}

LRESULT WinampFrame::onButton(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
	if (::IsWindow(hwndWinamp)) {
		switch(wID) {
			case IDC_PLAY: 
				{
					int i = ctrlList.GetNextItem(-1, LVNI_SELECTED);
					if(i < 0) {
						return 0;
					}
					SendMessage(hwndWinamp, WM_WA_IPC, i, IPC_SETPLAYLISTPOS);
					SendMessage(hwndWinamp, WM_COMMAND, WINAMP_BUTTON2, 0); 
				}
				break;
			case IDC_STOP: SendMessage(hwndWinamp, WM_COMMAND, WINAMP_BUTTON4, 0); break;
			case IDC_PAUSE: SendMessage(hwndWinamp, WM_COMMAND, WINAMP_BUTTON3, 0); break;	
			case IDC_REFRESH_WINAMP: refresh(); break;	
		}
	}
	return 0;
}

LRESULT WinampFrame::onDblClick(int idCtrl, LPNMHDR /* pnmh */, BOOL& bHandled) {
	if (::IsWindow(hwndWinamp)) {
		SendMessage(hwndWinamp,WM_WA_IPC,idCtrl,IPC_SETPLAYLISTPOS);
		return onButton(0, IDC_PLAY, 0, bHandled);
	} else {
		return 0;
	}
}
void WinampFrame::loadAll() {
	if (::IsWindow(hwndWinamp)) {
		int waVersion = SendMessage(hwndWinamp,WM_USER, 0, IPC_GETVERSION),
			majorVersion, minorVersion;
		majorVersion = waVersion >> 12;
		if (((waVersion & 0x00F0) >> 4) == 0) {
			minorVersion = ((waVersion & 0x0f00) >> 8) * 10 + (waVersion & 0x000f);
		} else {
			minorVersion = ((waVersion & 0x00f0) >> 4) * 10 + (waVersion & 0x000f);
		}
		string title = STRING(MENU_WINAMP) + " " + Util::toString(majorVersion + minorVersion / 100.0);
		SetWindowText(title.c_str());
		loadm3u();
		
		ctrlList.SelectItem(SendMessage(hwndWinamp,WM_WA_IPC,0,IPC_GETLISTPOS));
		ctrlPosition.SetRange(0, SendMessage(hwndWinamp,WM_USER, 1, IPC_GETOUTPUTTIME));
	}
}

void WinampFrame::setStatus() {
	if(ctrlStatus.IsWindow() && ::IsWindow(hwndWinamp)) {
		CRect sr;
		int w[4];
		ctrlStatus.GetClientRect(sr);

		int tmp = (sr.Width() / 4) - 4;
		
		w[0] = tmp;
		w[1] = w[0] + tmp;
		w[2] = w[1] + tmp;
		w[3] = w[2] + tmp;
		
		ctrlStatus.SetParts(4, w);
		TCHAR titleBuffer[2048];
		int buffLength = sizeof(titleBuffer);
		string title;
		string::size_type x;
		
		int curPos(-1), length(0), pos(0), waSampleRate(0), waBitRate(0), waChannels(0), state(0);
		if(::IsWindow(hwndWinamp)) { curPos = SendMessage(hwndWinamp,WM_USER, 0, IPC_GETOUTPUTTIME); }
		if(::IsWindow(hwndWinamp) ){ length = SendMessage(hwndWinamp,WM_USER, 1, IPC_GETOUTPUTTIME); }
		if (curPos == -1) {
			curPos = 0;
		} else {
			curPos /= 1000;
		}
		int intPercent;
		if (length > 0 ) {
			intPercent = curPos * 100 / length;
		} else {
			length = 0;
			intPercent = 0;
		}
		if(::IsWindow(hwndWinamp)) { pos = SendMessage(hwndWinamp,WM_WA_IPC,0,IPC_GETLISTPOS); }
		if(::IsWindow(hwndWinamp)) { 
			::GetWindowText(hwndWinamp, titleBuffer, buffLength); 
			title = titleBuffer;
			title = title.substr(title.find(".")+2, title.size());
			if ( (x = title.rfind("-")) != string::npos ) {
				title = title.substr(0, x/*title.rfind("-")-1*/);
			}
			
			if(pos != oldPos) {
				if ( (x = title.rfind(" - ")) != string::npos ) {
					ctrlList.SetItemText(pos, 0, title.substr(0, x).c_str());
					ctrlList.SetItemText(pos, 1, title.substr(x+3).c_str());
				} else {
					ctrlList.SetItemText(pos, 0, title.c_str());
				}
			}
		} else {
			title = "";
		}
		ctrlStatus.SetText(0, title.c_str());
		title = Util::formatPlaytime(length);
		if(pos != oldPos) {
			ctrlList.SetItemText(pos, 2, title.c_str());
			ctrlList.RedrawItems(pos, pos);
			ctrlList.RedrawItems(oldPos, oldPos);
			oldPos = pos;
			ctrlPosition.SetRange(0, length);
		}
		if(!dragging) {
			ctrlPosition.SetPos(curPos);
		}
		title = Util::toString(intPercent) + "% : " + Util::formatPlaytime(curPos) + " : " + title;
		ctrlStatus.SetText(1, title.c_str());
		if(::IsWindow(hwndWinamp)) {
			waSampleRate = SendMessage(hwndWinamp,WM_USER, 0, IPC_GETINFO);
			waBitRate = SendMessage(hwndWinamp,WM_USER, 1, IPC_GETINFO);
			waChannels = SendMessage(hwndWinamp,WM_USER, 2, IPC_GETINFO);
		}
		title = Util::toString(waBitRate) + STRING(WINAMP_KBPS) + " : " + Util::toString(waSampleRate) + STRING(WINAMP_KHZ) + " : " + (waChannels==2?STRING(WINAMP_STEREO):STRING(WINAMP_MONO));
		ctrlStatus.SetText(2, title.c_str());

		if(::IsWindow(hwndWinamp)) { state = SendMessage(hwndWinamp,WM_USER, 0, IPC_ISPLAYING); }
		switch (state) {
			case 0: title = "stopped";
				break;
			case 1: title = "playing";
				break;
			case 3: title = "paused";
		};
		ctrlStatus.SetText(3, title.c_str());
	}
}

void WinampFrame::on(TimerManagerListener::Second, DWORD /*aTick*/) throw() {
		setStatus();
}

LRESULT WinampFrame::onCustomDraw(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) {
	LPNMLVCUSTOMDRAW cd = (LPNMLVCUSTOMDRAW)pnmh;

	switch(cd->nmcd.dwDrawStage) {
	case CDDS_PREPAINT:
		return CDRF_NOTIFYITEMDRAW;

	case CDDS_ITEMPREPAINT:
		{
			if(::IsWindow(hwndWinamp)) {
				cd->clrText = ((int)cd->nmcd.dwItemSpec == SendMessage(hwndWinamp,WM_WA_IPC,0,IPC_GETLISTPOS)) ? SETTING(FILELIST_AND_CLIENT_CHECKED_COLOUR) : WinUtil::textColor;
				return CDRF_NEWFONT | CDRF_NOTIFYSUBITEMDRAW;
			}
		}
		return CDRF_NOTIFYSUBITEMDRAW;

	default:
		return CDRF_DODEFAULT;
	}
}
LRESULT WinampFrame::onTrackBarRelease(int /*idCtrl*/, LPNMHDR /* pnmh */, BOOL& /*bHandled*/) {
	if(::IsWindow(hwndWinamp)) {
		SendMessage(hwndWinamp,WM_WA_IPC,ctrlPosition.GetPos()*1000,IPC_JUMPTOTIME);
	}
	return 0;
}

void WinampFrame::refresh() {
	ctrlList.SetRedraw(FALSE);
	if(::IsWindow(hwndWinamp)) {
		SendMessage(hwndWinamp, WM_WA_IPC, 0, IPC_WRITEPLAYLIST);
		ctrlList.DeleteAllItems();
		loadm3u();
	}
	ctrlList.SetRedraw(TRUE);
}

void WinampFrame::loadm3u() {
	string playList;
	try {
		playList = File(SETTING(WINAMP_LOCATION) + "\\winamp.m3u", File::READ, File::OPEN).read();
	} catch(const FileException&) {
		return;
	}
	StringTokenizer<string> t(playList, '\n');
	StringList& tokens = t.getTokens();
	int pos = 0;
	StringList line;
	string::size_type x, y;
	string tmp;
	bool hasInfo = false;
	for(StringIter i = tokens.begin(); i != tokens.end(); ++i) {
		tmp = i->substr(0, i->size()-1);
		if(tmp.find("#EXTM3U") == string::npos) {
			if( (x = tmp.find("#EXTINF:")) != string::npos ) {
				if( (y = tmp.find(",")) != string::npos ) {
					if( (x = tmp.rfind(" - ")) != string::npos ) {
						line.push_back(tmp.substr(y+1, x-y-1));
						line.push_back(tmp.substr(x+3));
					} else {
						line.push_back(tmp.substr(y+1));
						line.push_back("");
					}
					line.push_back(Util::formatTime("%M:%S", Util::toInt(tmp.substr(8, y-8))));
				} else {
					line.push_back("");
					line.push_back("");
					line.push_back("");
				}
				hasInfo = true;
			} else {
				if(!hasInfo) {
					line.push_back("");
					line.push_back("");
					line.push_back("");
				}
				if( (x = tmp.rfind("\\")) != string::npos) {
					line.push_back(tmp.substr(x+1));
					line.push_back(tmp.substr(0, x));
				} else {
					line.push_back("");
					line.push_back("");
				}
				ctrlList.insert(pos, line);
				line.clear();
				pos++;
				hasInfo = false;
			}
		}
	}
}